//License: Artistic License v2.0, http://opensource.org/licenses/Artistic-2.0

package main

import (
	"compress/gzip"
	"io/ioutil"
	"log"
	"os"
	"strings"
)

//Gz reads either a file or string and returns the gzipped content.
//If fname is not empty, it returns gzipped file.  Otherwise, it returns gzipped string.
//If input is string or css/js/json/html/xml file, it will StripEmptyChars first.
func Gz(fname, str string) (buf []byte) {
	var err error
	if fname != "" {
		if buf, err = ioutil.ReadFile(fname); err != nil {
			log.Println(err)
			return []byte{}
		}
		switch GetFileExtension(fname) {
		case "css", "js", "json", "html", "htm", "xml":
			buf = []byte(StripEmptyChars(string(buf)))
		}
	} else {
		buf = []byte(StripEmptyChars(str))
	}
	f, err := ioutil.TempFile("", "gz")
	defer f.Close()
	if err != nil {
		log.Println(err)
		return []byte{}
	}
	gz, err := gzip.NewWriterLevel(f, gzip.BestCompression)
	//alternatively, we can use gzip.NewWriter(f)
	if err != nil {
		log.Println(err)
		return []byte{}
	}
	if _, err = gz.Write(buf); err != nil {
		log.Println(err)
		return []byte{}
	}
	gz.Close()
	if buf, err = ioutil.ReadFile(f.Name()); err != nil {
		log.Println(err)
		return []byte{}
	}
	if err = os.Remove(f.Name()); err != nil {
		log.Println(err)
	}
	return buf
}

func StripEmptyChars(str string) string {
	buf := []byte(str)
	strippedBytes := make([]byte, 0)
	for i := 0; i < len(buf); i++ {
		switch buf[i] {
		case '\n', '\r', '\f', '\t', '\v':
			continue //skip newline, carriage return, form feed, horizontal tab, vertical tab
		}
		strippedBytes = append(strippedBytes, buf[i])
	}
	return string(strippedBytes)
}

func GetFileExtension(str string) string {
	var tmp []string = strings.Split(str, ".")
	if len(tmp) < 2 {
		return ""
	}
	return strings.ToLower(tmp[len(tmp)-1])
}

//Copyright: Slamet Hendry
